package com.linkoog.devtools.project_manager.settings;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.util.ui.ListTableModel;
import com.linkoog.devtools.project_manager.ProjectScanner;
import com.linkoog.devtools.project_manager.settings.domain.ProjectDirectory;

import javax.swing.DefaultListModel;

import com.linkoog.devtools.project_manager.settings.domain.ProjectInfo;
import org.jetbrains.annotations.Nullable;
import javax.swing.JComponent;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import com.intellij.openapi.options.SearchableConfigurable;

public class ProjectManagerConfigurable implements SearchableConfigurable {

    private final ProjectManagerSetting persistenceSettings;
    private final ProjectManagerConfigurableUI configurableUI;
    
    public ProjectManagerConfigurable() {
        this.persistenceSettings = ProjectManagerSetting.getInstance();
        this.configurableUI = new ProjectManagerConfigurableUI();
    }
    
    @NotNull
    public String getId() {
        return "com.linkoog.devtools.project-switcher";
    }
    
    @Nls(capitalization = Nls.Capitalization.Title)
    public String getDisplayName() {
        return "Project Switcher";
    }
    
    @Nullable
    public JComponent createComponent() {
        return configurableUI.getMyMainPanel();
    }
    
    public boolean isModified() {
        final List<ProjectDirectory> modelItems = this.configurableUI.getModelItems();
        final TreeSet<ProjectDirectory> projectDirectorys = this.persistenceSettings.getProjectDirectorys();

        final Set<String> uiSet = modelItems.stream().map(ProjectDirectory::getPath).collect(Collectors.toUnmodifiableSet());
        final Set<String> persistSet = projectDirectorys.stream().map(ProjectDirectory::getPath).collect(Collectors.toUnmodifiableSet());
        if (uiSet.size() != persistSet.size()) {
            return true;
        }

        for (String modelItem : uiSet) {
            if (!persistSet.contains(modelItem)) {
                return true;
            }
        }

        return false;
    }
    
    public void apply() {
        final List<ProjectDirectory> modelItems = this.configurableUI.getModelItems();
        final Set<ProjectDirectory> projectDirectorys = this.persistenceSettings.getProjectDirectorys();

        Map<String, ProjectDirectory> uiMap = modelItems.stream().collect(Collectors.toMap(ProjectDirectory::getPath, Function.identity()));
        Map<String, ProjectDirectory> persistMap = projectDirectorys.stream().collect(Collectors.toMap(ProjectDirectory::getPath, Function.identity()));

        //删除的
        for (String path : persistMap.keySet()) {
            if (! uiMap.containsKey(path)){
                projectDirectorys.remove(persistMap.get(path));
            }
        }

        //新增的
        List<String> addPaths = new ArrayList<>();
        for (String path : uiMap.keySet()) {
            if (! persistMap.containsKey(path)){
                addPaths.add(path);
            }
        }


        ProgressManager.getInstance().run(new Task.Backgroundable(ProjectManager.getInstance().getDefaultProject(),"scan project...") {
            @Override
            public void run(@NotNull ProgressIndicator indicator) {
                for (String addPath : addPaths) {
                    final Path path = Paths.get(addPath);
                    final List<ProjectInfo> list = ProjectScanner.scan(path, indicator::setText2);

                    ProjectDirectory projectDirectory = new ProjectDirectory(path.getFileName().toString(), addPath, list);
                    projectDirectorys.add(projectDirectory);
                }
            }
        });
    }
    
    public void reset() {
        final ListTableModel<ProjectDirectory> defaultModel = this.configurableUI.getModel();
        defaultModel.setItems(new ArrayList<>());

        final Set<ProjectDirectory> projectDirectoryList = this.persistenceSettings.getProjectDirectorys();
        if (projectDirectoryList != null){
            defaultModel.setItems(new ArrayList<>(projectDirectoryList));
        }
    }
    
    private <E> Set<E> elementsAsSet(final DefaultListModel<E> defaultListModel) {
        final int size = defaultListModel.getSize();
        final Set<E> result = new HashSet<E>(size);
        for (int i = 0; i < size; ++i) {
            result.add(defaultListModel.get(i));
        }
        return result;
    }
}
